/*
 * HashBucket.cpp
 *
 *  Created on: Oct 18, 2012
 *      Author: Federico Orquera
 */

/*
 *
 * REVISAR SI ESTO NOS PUEDE SER UTIL PARA EL ERASE!
 *
 void HashBucket::resetBucket() {
 td = 1;
 numberOfRecords = 0;
 }
 */

#include "HashBucket.h"
#include <iostream>


HashBucket::HR_LIST_ptr HashBucket::emptyRecordListPointer;
HashBucketSerializer HashBucket::m_serializer;

HashBucket::HashBucket( size_t capacity, BucketID bucketId, TypeTD td, HR_LIST_ptr& records ) :
        m_maxCapacity( capacity ), m_bucketId( bucketId ), m_td( td ),
        m_records()
{
    if ( records == emptyRecordListPointer )
        m_records.reset( new HR_LIST );
    else
        m_records = records;
}

HashBucket::HashBucket( TypeTD td, HR_LIST_ptr &records ) :
    m_maxCapacity( 0 ), m_bucketId( 0 ), m_td( td ),
    m_records( records )
{
}

HashBucket::~HashBucket()
{
}

HashBucket::BucketID HashBucket::getBucketNr() const
{
    return m_bucketId;
}

HashBucket::TypeTD HashBucket::getTd() const
{
    return m_td;
}

void HashBucket::setTd( TypeTD td )
{
    this->m_td = td;
}

HashRecord* HashBucket::getRecord( RecordID id )
{
    HR_LIST::iterator it;
    for ( it = m_records->begin(); it != m_records->end(); it++ )
        if ( (*it)->getId() == id )
            return it->get();

    return NULL;
}

void HashBucket::deleteRecord( RecordID id )
{
    HR_LIST::iterator it;
    for ( it = m_records->begin(); it != m_records->end(); it++ )
    {
        if ( (*it)->getId() == id )
        {
            m_records->erase( it );
            break;
        }
    }
}


bool HashBucket::recordExists( RecordID id )
{
    bool recordExists = false;

    HR_LIST::iterator it;
    for ( it = m_records->begin(); it != m_records->end(); it++ )
        if ( (*it)->getId() == id )
        {
            recordExists = true;
            break;
        }

    return recordExists;
}

// TODO: la unicidad de alta en el hashBucket se implementa a nivel lógico (en archivoDirecto) con el método recordExist
bool HashBucket::addRegister( RecordID id, const std::string& frase,
        const std::string& apellidoAutor, const std::string& nombreAutor )
{
    size_t currentSize;
    bool result;

    // Este es más complicado, porque tiene que agregarlo a la lista, calcular el tamaño de la lista
    //    y si el tamaño de la lista (o del bucket) es mayor al tamaño del bloque, entonces lo saca y
    //    devuelve false

    HR_ptr newRecord( new HashRecord( id, frase, apellidoAutor, nombreAutor ) );
    m_records->push_back( newRecord );

    // Calcular el tamaño que ocupa el bucket en este momento
    currentSize = m_serializer.computeSize( *this );

    // Si la suma da menor o igual a la capacidad del bloque ( cuidado con el factor!! ) insertar el
    //   nuevo registro en la lista y devolver true, sino NO insertarlo y devolver false.
    if ( currentSize <= m_maxCapacity )
    {
        result = true;
    }
    else
    {
        result = false;
        m_records->pop_back();
    }

    return result;
}
